package com.echo.im.common.util;

import com.alibaba.fastjson2.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;

public final class JwtUtil {

    private static final String secret = "IKDiqVmn0VFU";

    private JwtUtil() {
    }

    /**
     * 生成一个有过期时间的临时 JWT 令牌
     *
     * @param business 业务标识
     * @param userId   用户 ID
     * @param info     用户信息
     * @param expireIn 过期时间（秒）
     * @return 生成的 JWT 令牌，如果生成失败则返回 null
     */
    public static String createTempToken(String business, String userId, Object info, long expireIn) {
        try {
            Date date = new Date(System.currentTimeMillis() + expireIn * 1000);
            Algorithm algorithm = Algorithm.HMAC256(secret);
            return JWT.create()
                    .withClaim("business", business)
                    .withClaim("info", JSONObject.toJSONString(info))
                    .withClaim("userId", userId)
                    //过期时间
                    .withExpiresAt(date)
                    //token的密钥
                    .sign(algorithm);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 解析并校验临时令牌，并返回一个指定类型的信息对象
     *
     * @param business 业务标识
     * @param userId   用户ID
     * @param token    令牌字符串
     * @param clazz    信息类的类型
     * @return 指定类型的信息对象，如果令牌无效或校验失败则返回null
     */
    public static <T> T parseAndCheckTempToken(String business, String userId, String token, Class<T> clazz) {
        try {
            // 验证是否有效
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm).build();
            verifier.verify(token);

            DecodedJWT decodedJWT = JWT.decode(token);
            if (!business.equals(decodedJWT.getClaim("business").asString())) {
                return null;
            }

            // 验证临时token使用者
            if (!userId.equals(decodedJWT.getClaim("userId").asString())) {
                return null;
            }

            // 返回指定类型的信息类
            String infoJson = decodedJWT.getClaim("info").asString();
            return JSONObject.parseObject(infoJson, clazz);

        } catch (Exception e) {
            return null;
        }
    }

}
